package org.setec.config;

import org.setec.utils.xml.XMLUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

//v2
public class ConfigLoader {

    public static InterpretableConfiguration load(String path) {
        try {
            return parse(readFile(new File(path)));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static InterpretableConfiguration load(InputStream stream) {
        try {
            return parse(readStream(stream));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static InterpretableConfiguration parse(String xml) {
        InterpretableConfiguration result = new InterpretableConfiguration();
        XMLNode root = new XMLNode(xml);

        result.setMode(root.getChildNode("settings", 0).getChildNode("mode", 0).getAttribute("value"));
        result.setStorage(root.getChildNode("settings", 0).getChildNode("storage", 0).getAttribute("path"));

        List aspects = new ArrayList();
        result.setAspectList(aspects);
        XMLNode aspectsNode = root.getChildNode("aspects", 0);
        for (int i = 0; i < aspectsNode.getChildNumber("aspect"); i++) {
            XMLNode aspectNode = aspectsNode.getChildNode("aspect", i);
            Aspect aspect = new Aspect();
            aspect.setClassName(aspectNode.getAttribute("class"));
            List joinPoints = new ArrayList();
            aspect.setJoinPoints(joinPoints);
            for (int j = 0; j < aspectNode.getChildNumber("joinpoint"); j++) {
                XMLNode joinPointNode = aspectNode.getChildNode("joinpoint", i);
                String methodSignature = joinPointNode.getAttribute("method");
                JoinPoint joinPoint = new JoinPoint(methodSignature);
                joinPoints.add(joinPoint);
                for( int k = 0; k < joinPointNode.getChildNumber("invalidate"); k++ ){
                    XMLNode invalidateNode = joinPointNode.getChildNode("invalidate", 0);
                    InvalidateDetails invalidateDetails = new InvalidateDetails();
                    invalidateDetails.setKey(invalidateNode.getAttribute("key"));
                    invalidateDetails.setWhen(invalidateNode.getAttribute("when"));
                    invalidateDetails.setContext(invalidateNode.getAttribute("context"));
                    joinPoint.getInvalidateDetails().add(invalidateDetails);
                }
            }
            aspect.setJoinPoints(joinPoints);
            aspects.add(aspect);
        }
        return result;
    }


    private static void streamData(InputStream input, OutputStream output) throws IOException {
        InputStream inputBuffer = null;
        OutputStream outputBuffer = null;
        try {
            inputBuffer = new BufferedInputStream(input);
            outputBuffer = new BufferedOutputStream(output);
            while (true) {
                int data = inputBuffer.read();
                if (data == -1) {
                    break;
                }
                outputBuffer.write(data);
            }
        } finally {
            if (inputBuffer != null) {
                inputBuffer.close();
            }
            if (outputBuffer != null) {
                outputBuffer.close();
            }
        }
    }

    private  static String readFile(File file) throws IOException {
        FileInputStream fileInputStream = new FileInputStream(file);
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1000);
        streamData(fileInputStream, byteArrayOutputStream);
        return new String(byteArrayOutputStream.toByteArray());
    }

    private static String readStream(InputStream stream) throws IOException {
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1000);
        streamData(stream, byteArrayOutputStream);
        return new String(byteArrayOutputStream.toByteArray());
    }

}